/*
 * Copyright (c) 2009-2024 Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the License); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*============================ INCLUDES ======================================*/

#define __USER_SCENE1_IMPLEMENT__
#include "arm_2d_scenes.h"

#if defined(RTE_Acceleration_Arm_2D_Helper_PFB)

#ifdef RTE_Acceleration_Arm_2D_Scene1

#include <stdlib.h>
#include <string.h>

#if defined(__clang__)
#   pragma clang diagnostic push
#   pragma clang diagnostic ignored "-Wunknown-warning-option"
#   pragma clang diagnostic ignored "-Wreserved-identifier"
#   pragma clang diagnostic ignored "-Wsign-conversion"
#   pragma clang diagnostic ignored "-Wpadded"
#   pragma clang diagnostic ignored "-Wcast-qual"
#   pragma clang diagnostic ignored "-Wcast-align"
#   pragma clang diagnostic ignored "-Wmissing-field-initializers"
#   pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#   pragma clang diagnostic ignored "-Wmissing-prototypes"
#   pragma clang diagnostic ignored "-Wunused-variable"
#   pragma clang diagnostic ignored "-Wgnu-statement-expression"
#   pragma clang diagnostic ignored "-Wdeclaration-after-statement"
#   pragma clang diagnostic ignored "-Wunused-function"
#   pragma clang diagnostic ignored "-Wmissing-declarations"
#   pragma clang diagnostic ignored "-Wimplicit-int-conversion" 
#elif __IS_COMPILER_ARM_COMPILER_5__
#   pragma diag_suppress 64,177
#elif __IS_COMPILER_IAR__
#   pragma diag_suppress=Pa089,Pe188,Pe177,Pe174
#elif __IS_COMPILER_GCC__
#   pragma GCC diagnostic push
#   pragma GCC diagnostic ignored "-Wformat="
#   pragma GCC diagnostic ignored "-Wpedantic"
#   pragma GCC diagnostic ignored "-Wunused-function"
#   pragma GCC diagnostic ignored "-Wunused-variable"
#   pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
#endif

/*============================ MACROS ========================================*/

#if __GLCD_CFG_COLOUR_DEPTH__ == 8

#   define c_tileCMSISLogo          c_tileCMSISLogoGRAY8

#elif __GLCD_CFG_COLOUR_DEPTH__ == 16

#   define c_tileCMSISLogo          c_tileCMSISLogoRGB565

#elif __GLCD_CFG_COLOUR_DEPTH__ == 32

#   define c_tileCMSISLogo          c_tileCMSISLogoCCCA8888
#else
#   error Unsupported colour depth!
#endif

/*============================ MACROFIED FUNCTIONS ===========================*/
#undef this
#define this (*ptThis)

/*============================ TYPES =========================================*/
/*============================ GLOBAL VARIABLES ==============================*/

extern const arm_2d_tile_t c_tileCMSISLogo;
extern const arm_2d_tile_t c_tileCMSISLogoMask;
extern const arm_2d_tile_t c_tileCMSISLogoA2Mask;
extern const arm_2d_tile_t c_tileCMSISLogoA4Mask;
/*============================ PROTOTYPES ====================================*/
/*============================ LOCAL VARIABLES ===============================*/
void  draw_string_2d(uint16_t iX,uint16_t iY,char font_size,char *strin,
    void *pTarget,                                  
                                const arm_2d_tile_t *ptTile);
/*! define dirty regions */
IMPL_ARM_2D_REGION_LIST(s_tDirtyRegions, static)

    /* a dirty region to be specified at runtime*/
    ADD_REGION_TO_LIST(s_tDirtyRegions,
        0  /* initialize at runtime later */
    ),
    
    /* add the last region:
        * it is the top left corner for text display 
        */
    ADD_LAST_REGION_TO_LIST(s_tDirtyRegions,
        .tLocation = {
            .iX = 0,
            .iY = 0,
        },
        .tSize = {
            .iWidth = 0,
            .iHeight = 8,
        },
    ),

END_IMPL_ARM_2D_REGION_LIST(s_tDirtyRegions)

/*============================ IMPLEMENTATION ================================*/

static void __on_scene1_load(arm_2d_scene_t *ptScene)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}

static void __after_scene1_switching(arm_2d_scene_t *ptScene)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}

static void __on_scene1_depose(arm_2d_scene_t *ptScene)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)ptScene;
    ARM_2D_UNUSED(ptThis);
    
    ptScene->ptPlayer = NULL;
    
    /* reset timestamp */
    arm_foreach(int64_t,this.lTimestamp, ptItem) {
        *ptItem = 0;
    }

    if (!this.bUserAllocated) {
        __arm_2d_free_scratch_memory(ARM_2D_MEM_TYPE_UNSPECIFIED, ptScene);
    }
}

/*----------------------------------------------------------------------------*
 * Scene 1                                                                    *
 *----------------------------------------------------------------------------*/

static void __on_scene1_background_start(arm_2d_scene_t *ptScene)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}

static void __on_scene1_background_complete(arm_2d_scene_t *ptScene)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}

void book_run(arm_2d_scene_t *ptScene);
static void __on_scene1_frame_start(arm_2d_scene_t *ptScene)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)ptScene;
    ARM_2D_UNUSED(ptThis);
    book_run(ptScene);

}

static void __on_scene1_frame_complete(arm_2d_scene_t *ptScene)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

#if 0
    /* switch to next scene after 3s */
    if (arm_2d_helper_is_time_out(3000, &this.lTimestamp[0])) {
        arm_2d_scene_player_switch_to_next_scene(ptScene->ptPlayer);
    }
#endif
}

static void __before_scene1_switching_out(arm_2d_scene_t *ptScene)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}
void draw_book(void *pTarget,                                  
                                const arm_2d_tile_t *ptTile,
                                arm_2d_region_t my_region,    
                                bool bIsNewFrame);
static
IMPL_PFB_ON_DRAW(__pfb_draw_scene1_handler)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)pTarget;
    arm_2d_size_t tScreenSize = ptTile->tRegion.tSize;

    ARM_2D_UNUSED(ptTile);
    ARM_2D_UNUSED(bIsNewFrame);
    ARM_2D_UNUSED(tScreenSize);
    
    arm_2d_fill_colour(ptTile, NULL, GLCD_COLOR_BLACK);
    
    arm_2d_canvas(ptTile, __top_canvas) {
    /*-----------------------draw the foreground begin-----------------------*/
        draw_book( pTarget,                                  
                                 ptTile,
                                  __top_canvas,    
                                  bIsNewFrame);    
       


    

        /* draw text at the top-left corner */

        arm_lcd_text_set_target_framebuffer((arm_2d_tile_t *)ptTile);
        arm_lcd_text_set_font(&ARM_2D_FONT_6x8.use_as__arm_2d_font_t);
        arm_lcd_text_set_draw_region(NULL);
        arm_lcd_text_set_colour(GLCD_COLOR_WHITE, GLCD_COLOR_BLACK);
        arm_lcd_text_location(0,0);
        //arm_lcd_puts("Scene 1");

    /*-----------------------draw the foreground end  -----------------------*/
    }
    ARM_2D_OP_WAIT_ASYNC();

    return arm_fsm_rt_cpl;
}
void my_book_init1();
void my_book_init();
ARM_NONNULL(1)
user_scene_1_t *__arm_2d_scene1_init(   arm_2d_scene_player_t *ptDispAdapter, 
                                        user_scene_1_t *ptThis)
{
    bool bUserAllocated = false;
    assert(NULL != ptDispAdapter);

    s_tDirtyRegions[dimof(s_tDirtyRegions)-1].ptNext = NULL;

    /* get the screen region */
    arm_2d_region_t tScreen
        = arm_2d_helper_pfb_get_display_area(
            &ptDispAdapter->use_as__arm_2d_helper_pfb_t);

    /* initialise dirty region 0 at runtime
     * this demo shows that we create a region in the centre of a screen(320*240)
     * for a image stored in the tile c_tileCMSISLogoMask
     */
    arm_2d_align_centre(tScreen, c_tileCMSISLogoMask.tRegion.tSize) {
        s_tDirtyRegions[0].tRegion = __centre_region;
    }

    s_tDirtyRegions[dimof(s_tDirtyRegions)-1].tRegion.tSize.iWidth 
                                                        = tScreen.tSize.iWidth;
    
    if (NULL == ptThis) {
        ptThis = (user_scene_1_t *)
                    __arm_2d_allocate_scratch_memory(   sizeof(user_scene_1_t),
                                                        __alignof__(user_scene_1_t),
                                                        ARM_2D_MEM_TYPE_UNSPECIFIED);
        assert(NULL != ptThis);
        if (NULL == ptThis) {
            return NULL;
        }
    } else {
        bUserAllocated = true;
    }
    memset(ptThis, 0, sizeof(user_scene_1_t));

    *ptThis = (user_scene_1_t){
        .use_as__arm_2d_scene_t = {

            /* the canvas colour */
            .tCanvas = {GLCD_COLOR_WHITE}, 

            /* Please uncommon the callbacks if you need them
             */
            .fnOnLoad       = &__on_scene1_load,
            .fnScene        = &__pfb_draw_scene1_handler,
            //.fnAfterSwitch  = &__after_scene1_switching,

            /* if you want to use predefined dirty region list, please uncomment the following code */
            //.ptDirtyRegion  = (arm_2d_region_list_item_t *)s_tDirtyRegions,
            

            //.fnOnBGStart    = &__on_scene1_background_start,
            //.fnOnBGComplete = &__on_scene1_background_complete,
            .fnOnFrameStart = &__on_scene1_frame_start,
            //.fnBeforeSwitchOut = &__before_scene1_switching_out,
            .fnOnFrameCPL   = &__on_scene1_frame_complete,
            .fnDepose       = &__on_scene1_depose,

            .bUseDirtyRegionHelper = false,
        },
        .bUserAllocated = bUserAllocated,
    };

    /* ------------   initialize members of user_scene_1_t begin ---------------*/


    /* ------------   initialize members of user_scene_1_t end   ---------------*/

    arm_2d_scene_player_append_scenes(  ptDispAdapter, 
                                        &this.use_as__arm_2d_scene_t, 
                                        1);
    //  my_book_init1();
    my_book_init();                                    
    return ptThis;
}
//====================================================================================================
#include "ff.h" 
#include "key.h"
#define BOOK_PATH_NEWFILE_TXT "/TXT/list.txt"
#define BOOK_TOTAL_LINE 4 
typedef struct book_t{
    uint16_t total_count;
    uint16_t current_num;
    uint32_t  current_lseek;
    uint32_t book_size;
    uint16_t add_lseek;
    char lines[BOOK_TOTAL_LINE][17];
    char list_read_flag;
    char book_name[50];
}book_t;

book_t my_book;
void my_book_total_num_init(){
    FIL file;  // 文件对象
    FRESULT res;  // FatFs返回结果
    FILINFO fno;  // 文件信息结构体
    
    res = f_open(&file,  BOOK_PATH_NEWFILE_TXT, FA_READ);
    if (res == FR_OK) {
        // 获取文件状态
        res = f_stat(BOOK_PATH_NEWFILE_TXT, &fno);
        if (res == FR_OK) {
            // 如果成功，将文件大小存储在提供的指针中
            //size = fno.fsize;
            //num = fno.fsize / 128;
            //my_book.book_num = fno.fsize / 128;
            my_book.total_count = fno.fsize / 128;
        }
        f_close(&file) ;  
    }
}
void my_book_init(){
    
    
    my_book.current_num = 0;
    my_book_total_num_init();
    my_book.list_read_flag = 1;
    my_book.current_lseek = 0;
}

void  draw_book_list(void *pTarget,                                  
                                const arm_2d_tile_t *ptTile,
                                arm_2d_region_t my_region,    
                                bool bIsNewFrame){
    FIL file;  // 文件对象
    FRESULT res;  // FatFs返回结果
    char out_buff[128];
    uint32_t rd_len;                                
                                    
    res = f_open(&file,  BOOK_PATH_NEWFILE_TXT, FA_READ);
    if (res == FR_OK) { 
        for(int i = 0; i < my_book.total_count; i++){
            res = f_lseek(&file, i*128);
            if (res == FR_OK) {
                res = f_read(&file, out_buff, 128, &rd_len);
                //draw_string(0,16,16,out_buff);
                draw_string_2d(10,
                                16*i,
                                16,out_buff,  pTarget,  ptTile);
            }
        }    
        
        
    }
    f_close(&file) ; 
    arm_2d_region_t  region={
             .tLocation = {
            .iX = 2,
            .iY = 0,
        },
        .tSize = {
            .iWidth = 120,
            .iHeight = 16,
        },
    }; 
    region.tLocation.iY = 16 *  my_book.current_num;   
    arm_2d_filter_reverse_colour(ptTile, 
                                        &region); 
        
    
}
void book_list_previous(){
    if( 0 == my_book.current_num){
        my_book.current_num = my_book.total_count;
    }
    my_book.current_num--;
}  
void book_list_next(){
    my_book.current_num++;
    my_book.current_num = my_book.current_num % my_book.total_count;
}
void read_book_name(){
    FIL file;  // 文件对象
    FRESULT res;  // FatFs返回结果
    FILINFO fno;  // 文件信息结构体
    char out_buff[128];
    uint32_t rd_len;                                
                                    
    res = f_open(&file,  BOOK_PATH_NEWFILE_TXT, FA_READ);
    if (res == FR_OK) { 
        //for(int i = 0; i < my_book.total_count; i++){
            res = f_lseek(&file, my_book.current_num *128);
            if (res == FR_OK) {
                res = f_read(&file, out_buff, 128, &rd_len);
                strcpy(my_book.book_name,"/TXT/"); 
                strcpy(&my_book.book_name[5],out_buff); 
            }
        //}    
        
        
    }
    f_close(&file) ; 
    
    //my_book.book_size;
    res = f_open(&file,  my_book.book_name, FA_READ);
    if (res == FR_OK) {
        // 获取文件状态
        res = f_stat(my_book.book_name, &fno);
        if (res == FR_OK) {
             
            my_book.book_size = fno.fsize ;
        }
    }
    f_close(&file) ; 
}
void book_list_run(){
     char key;
    key = get_g_key_num();
    if(key){
        switch (key){
            case 1:
                book_list_previous();
            break;
            case 3:
                book_list_next();
            break;
            case 2:
                read_book_name();
                my_book.list_read_flag = 2;
            break;
        }
        set_g_key_num(0);
    }
} 

//=============================================================
//lines[BOOK_TOTAL_LINE][17];
void write_line(arm_2d_region_t my_region,char *buff,char char_size){
    int i;
    int width = 0;
    int num = 0;
    my_book.add_lseek = 0;
    for(i = 0; i < BOOK_TOTAL_LINE;i++ ){
        width = 0;
        num = 0;
        while(1){
            if(width >= (my_region.tSize.iWidth - char_size) ){
                my_book.add_lseek +=  num;
                my_book.lines[i][num] = 0; 
                break;
            }
            if(*buff < 0x80){
                width += char_size / 2; 
                
                my_book.lines[i][num] = *buff; 
                buff++; 
                num++;    
            }else{
                width += char_size ; 
                my_book.lines[i][num] = *buff; 
                my_book.lines[i][num+1] = *(buff+1);      
                buff += 2;
                num  += 2;   
            }
           
        }
    }
}
void  draw_book_read(void *pTarget,                                  
                                const arm_2d_tile_t *ptTile,
                                arm_2d_region_t my_region,    
                                bool bIsNewFrame){
    FIL file;  // 文件对象
    FRESULT res;  // FatFs返回结果
    char out_buff[128];
    uint32_t rd_len;                                
                                    
    res = f_open(&file, my_book.book_name  , FA_READ);
    if (res == FR_OK) { 
        //for(int i = 0; i < my_book.total_count; i++){
            res = f_lseek(&file, my_book.current_lseek);
            if (res == FR_OK) {
                res = f_read(&file, out_buff, 128, &rd_len);
                //draw_string(0,16,16,out_buff);
                
            }
        //}    
        
        
    }
    f_close(&file) ; 
    //out_buff[8] = 0;
    arm_2d_dock_left(my_region, 120){
        write_line(  __left_region,out_buff,16); 
        draw_string_2d(0, 16 * 0, 16,&my_book.lines[0][0],  pTarget,  ptTile);     
        draw_string_2d(0, 16 * 1, 16,&my_book.lines[1][0],  pTarget,  ptTile);  
        draw_string_2d(0, 16 * 2, 16,&my_book.lines[2][0],  pTarget,  ptTile);
        draw_string_2d(0, 16 * 3, 16,&my_book.lines[3][0],  pTarget,  ptTile); 

    } 
    arm_2d_dock_right(my_region, 11){
        arm_2d_dock_horizontal(__right_region, 2){
            arm_2d_fill_colour(ptTile, &__horizontal_region, GLCD_COLOR_WHITE);
            __horizontal_region.tLocation.iX -= 2;
            __horizontal_region.tLocation.iY =  128 * my_book.current_lseek / my_book.book_size;
            if(__horizontal_region.tLocation.iY >  125){
                __horizontal_region.tLocation.iY = 125;
            }
            __horizontal_region.tSize.iWidth = 6;
            __horizontal_region.tSize.iHeight = 3;
            arm_2d_fill_colour(ptTile, &__horizontal_region, GLCD_COLOR_WHITE);
        }
    }        
           
}
void book_read_run(arm_2d_scene_t *ptScene){
     char key;
    key = get_g_key_num();
    if(key){
        switch (key){
            case 1:
                //book_list_previous();
                my_book.current_lseek += my_book.add_lseek;
            break;
            case 3:
                //book_list_next();
            break;
            case 2:
                my_book.list_read_flag = 1;
                __arm_2d_scene0_init( &DISP0_ADAPTER ,NULL);
                arm_2d_scene_player_switch_to_next_scene(ptScene->ptPlayer);
            break;
        }
        set_g_key_num(0);
    }
}                                 
                                //==================================
//========================================================================
void book_run(arm_2d_scene_t *ptScene){
    if(2 == my_book.list_read_flag ){
        book_read_run(ptScene);
    }else{
        book_list_run();
    }
}                                
void draw_book(void *pTarget,                                  
                                const arm_2d_tile_t *ptTile,
                                arm_2d_region_t my_region,    
                                bool bIsNewFrame){
    if(2 == my_book.list_read_flag ){                                
        draw_book_read(pTarget,                                  
                 ptTile,
                 my_region,    
                 bIsNewFrame);
    }else{
        draw_book_list( pTarget,                                  
                 ptTile,
                 my_region,    
                 bIsNewFrame);
    }
}
                                

   
#define BOOK_PATH_FOLDER  "/TXT"

void my_book_init1(){
    FRESULT res;  // FatFs返回结果
    DIR dir;      // 目录对象
    FILINFO fno;  // 文件信息结构体
    
    char temp_buff[10][128];
    char i = 0;
    // 尝试打开目录
    res = f_opendir(&dir,  BOOK_PATH_FOLDER);
    if (res != FR_OK) {
        //printf("打开目录失败，错误码：%d\n", res);
        return;
    }
    
    // 循环读取目录项
    while (1) {
        res = f_readdir(&dir, &fno);  // 读取一个目录项
        if (res != FR_OK || fno.fname[0] == 0) break;  // 出错或到达目录尾部时退出循环
        if (fno.fattrib & AM_DIR) {
            // 这是一个目录
            //draw_string(0,0,16,fno.fname);
        }else{
            // 这是一个文件，尝试打开
            
            
            strcpy(&temp_buff[i][0],fno.fname);
            i++;
        }

    }
    f_closedir(&dir);  // 关闭目录
    
    FIL file;  // 文件对象
    UINT bw;
    // 以写入模式打开文件，如果不存在则创建
    if (f_open(&file, BOOK_PATH_NEWFILE_TXT, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) {
        //error("File open failed");
        return;
    }
    
   
    for(int j = 0; j < i; j++){
        res = f_lseek(&file, j*128);
        if (res == FR_OK) {
            //const char *data = "追加的数据\n";
            res = f_write(&file, &temp_buff[j][0], 128, &bw); // 写入数据
            f_sync(&file); // 刷新数据
        }
    }
    // 关闭文件
    if (f_close(&file) != FR_OK) {
        //error("File close failed");
        return;
    }
    
    //=========================
    char out_buff[128];
    uint32_t rd_len;
    res = f_open(&file,  BOOK_PATH_NEWFILE_TXT, FA_READ);
    if (res == FR_OK) {
        //printf("成功打开文件：%s\n", fno.fname);
        // 这里可以进行文件操作，例如读取内容等
        for(int j = 0; j < i; j++){
            res = f_lseek(&file, j*128);
            if (res == FR_OK) {
                res = f_read(&file, out_buff, 128, &rd_len);
                //draw_string(0,16,16,out_buff);
            }
        }
        
        f_close(&file) ;

    }
   
}

#if defined(__clang__)
#   pragma clang diagnostic pop
#endif

#endif

#endif

